home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dme / cmd1.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  23KB  |  1,242 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  * CMD1.C   (was TEXT1.C)
  9.  */
  10.  
  11. #include "defs.h"
  12.  
  13. Prototype void escapecomlinemode (void);
  14. Prototype void setpen (int);
  15. Prototype void text_cursor (int);
  16. Prototype int text_init (ED *, WIN *, struct NewWindow *);
  17. Prototype int text_switch (struct Window *);
  18. Prototype int text_sync (void);
  19. Prototype int text_load (void);
  20. Prototype int text_colno (void);
  21. Prototype int text_lineno (void);
  22. Prototype int text_lines (void);
  23. Prototype int text_cols (void);
  24. Prototype int text_imode (void);
  25. Prototype int text_tabsize (void);
  26. Prototype unsigned char *text_name (void);
  27. Prototype void text_uninit (void);
  28. Prototype void inversemode (int);
  29. Prototype void text_position (int, int);
  30. Prototype void displayblock (int);
  31. Prototype void text_redrawblock (int);
  32. Prototype void text_redisplaycurrline (void);
  33. Prototype void text_redisplay (void);
  34. Prototype void text_write (unsigned char *);
  35. Prototype void text_displayseg (int, int);
  36. Prototype void movetocursor (void);
  37. Prototype void do_up (void);
  38. Prototype void do_scrolldown (void);
  39. Prototype void do_scrollup (void);
  40. Prototype void do_down (void);
  41. Prototype void do_page (void);
  42. Prototype void do_downadd (void);
  43. Prototype void do_left (void);
  44. Prototype void do_right (void);
  45. Prototype void do_col (void);
  46. Prototype void do_tab (void);
  47. Prototype void do_backtab (void);
  48. Prototype void do_return (void);
  49. Prototype void do_bs (void);
  50. Prototype void do_recall (void);
  51. Prototype void do_esc (void);
  52. Prototype void do_del (void);
  53. Prototype void do_top (void);
  54. Prototype void do_bottom (void);
  55. Prototype void do_firstcolumn (void);
  56. Prototype void do_firstnb (void);
  57. Prototype void do_lastcolumn (void);
  58. Prototype void do_goto (void);
  59. Prototype void do_screentop (void);
  60. Prototype void do_screenbottom (void);
  61. Prototype void do_findstr (void);
  62. Prototype void do_findr (void);
  63. Prototype void do_find (void);
  64. Prototype void do_findmatch(void);
  65. Prototype void do_window(void);
  66. Prototype void search_operation (void);
  67. Prototype int case_strncmp (char *, char *, int);
  68.  
  69.  
  70. typedef struct Process PROC;
  71.  
  72. #define nomemory()  { memoryfail = 1; }
  73.  
  74. char RecallBuf[256];
  75.  
  76. void
  77. setpen(line)
  78. {
  79.     ED *ep = Ep;
  80.     RP *rp = ep->Win->RPort;
  81.  
  82.     short pen = (ep == BEp && line >= BSline && line <= BEline) ? ep->HGPen : ep->FGPen;
  83.     if (Comlinemode)
  84.     pen = ep->FGPen;
  85.     if (pen != rp->FgPen)
  86.     SetAPen(rp, pen);
  87. }
  88.  
  89. text_init(oldep, win, nw)
  90. ED *oldep;
  91. WIN *win;
  92. struct NewWindow *nw;
  93. {
  94.     ED *e;
  95.  
  96.     text_switch(NULL);
  97.     e = (ED *)allocb(sizeof(ED));
  98.     if (e == NULL)
  99.     return(0);
  100.     setmem(e, sizeof(ED), 0);
  101.     e->Win = win;
  102.     if (oldep) {
  103.     e->dirlock = (long)DupLock((BPTR)oldep->dirlock);
  104.  
  105.     movmem(&oldep->BeginConfig, &e->BeginConfig, (char *)&e->EndConfig - (char *)&e->BeginConfig);
  106.  
  107.     if (oldep->Font) {
  108.         e->Font = oldep->Font;
  109.         ++e->Font->tf_Accessors;
  110.         if (win)
  111.         SetFont(win->RPort, e->Font);
  112.     }
  113.     e->IWiny = oldep->IWiny + 16;
  114.     } else {
  115.     PROC *proc = (PROC *)FindTask(NULL);
  116.     e->dirlock = (long)DupLock((BPTR)proc->pr_CurrentDir);
  117.  
  118.     e->Insertmode = 1;
  119.     e->Tabstop = 4;
  120.     e->WWCol = -1;
  121.     e->Margin= 75;
  122.     e->FGPen = 1;
  123.     e->BGPen = 0;
  124.     e->HGPen = 2;
  125.     loadconfig(e);
  126.     }
  127.     e->Lines = 1;
  128.     e->Maxlines = 32;
  129.     e->List = (ubyte **)allocl(e->Maxlines);
  130.     e->List[0] = allocb(1);
  131.     e->List[0][0] = Current[0] = Clen = 0;
  132.     AddHead((LIST *)&DBase, (NODE *)e);
  133.     strcpy(e->Name, "unnamed");
  134.     Ep = e;
  135.  
  136.     if (nw) {
  137.     if (e->Winwidth && e->Winheight) {
  138.         nw->LeftEdge= e->Winx;
  139.         nw->TopEdge = e->Winy;
  140.         nw->Width    = e->Winwidth;
  141.         nw->Height    = e->Winheight;
  142.     } else {
  143.         nw->LeftEdge= 0;
  144.         nw->TopEdge = 0;
  145.         nw->Width    = 640;
  146.         nw->Height    = 200;
  147.     }
  148.     nw->DetailPen = e->BGPen;
  149.     nw->BlockPen  = e->FGPen;
  150.     }
  151.  
  152.     return(1);
  153. }
  154.  
  155. text_switch(win)
  156. WIN *win;
  157. {
  158.     ED *e;
  159.  
  160.     if (win)
  161.     text_sync();
  162.     if (win) {
  163.     for (e = (ED *)DBase.mlh_Head; e->Node.mln_Succ; e = (ED *)e->Node.mln_Succ) {
  164.         if (e->Win == win) {
  165.         Ep = e;
  166.         text_load();
  167.         if (!Ep->iconmode) {
  168.             set_window_params();
  169.             window_title();
  170.         }
  171.         return(1);
  172.         }
  173.     }
  174.     return(0);
  175.     }
  176. }
  177.  
  178.  
  179. text_sync()
  180. {
  181.     ED *ep = Ep;
  182.     char redraw = 0;
  183.     short len;
  184.     ubyte *ptr;
  185.  
  186.     for (len = strlen(Current) - 1; len >= 0 && Current[len] == ' '; --len)
  187.     Current[len] = '\0';
  188.     Clen = len + 1;
  189.     if (!Comlinemode) {
  190.     if (strlen(ep->List[ep->Line]) != Clen) {
  191.         if (ptr = allocb(Clen+1)) {
  192.         ep->Modified = 1;
  193.         Overide = 0;
  194.         FreeMem(ep->List[ep->Line], strlen(ep->List[ep->Line])+1);
  195.         ep->List[ep->Line] = ptr;
  196.         } else {
  197.         nomemory();
  198.         strcpy(Current, ep->List[ep->Line]);
  199.         Clen = strlen(Current);
  200.         }
  201.     } else {
  202.         if (strcmp(ep->List[ep->Line], Current)) {
  203.         ep->Modified = 1;
  204.         Overide = 0;
  205.         }
  206.     }
  207.     strcpy(ep->List[ep->Line], Current);
  208.     }
  209.     if (Nsu == 0) {
  210.     if (ep->Column - ep->Topcolumn >= Columns || ep->Column < ep->Topcolumn) {
  211.         redraw = 1;
  212.         ep->Topcolumn = ep->Column - (Columns>>1);
  213.         if (ep->Topcolumn < 0)
  214.         ep->Topcolumn = 0;
  215.     }
  216.     if (ep->Line - ep->Topline >= Rows || ep->Line < ep->Topline) {
  217.         redraw = 1;
  218.         ep->Topline = ep->Line - (Rows>>1);
  219.         if (ep->Topline < 0)
  220.         ep->Topline = 0;
  221.     }
  222.     }
  223.     while (ep->Column > Clen)
  224.     Current[Clen++] = ' ';
  225.     Current[Clen] = '\0';
  226.     if (redraw)
  227.     text_redisplay();
  228.     return((int)redraw);
  229. }
  230.  
  231. text_load()
  232. {
  233.     if (Comlinemode)
  234.     return(0);
  235.     strcpy(Current, Ep->List[Ep->Line]);
  236.     Clen = strlen(Current);
  237.     while (Ep->Column > Clen)
  238.     Current[Clen++] = ' ';
  239.     Current[Clen] = '\0';
  240. }
  241.  
  242. text_colno()
  243. {
  244.     return(Ep->Column);
  245. }
  246.  
  247. text_lineno()
  248. {
  249.     return(Ep->Line+1);
  250. }
  251.  
  252. text_lines()
  253. {
  254.     return(Ep->Lines);
  255. }
  256.  
  257. text_cols()
  258. {
  259.     return((int)Clen);
  260. }
  261.  
  262. text_imode()
  263. {
  264.     return((int)Ep->Insertmode);
  265. }
  266.  
  267. text_tabsize()
  268. {
  269.     return((int)Ep->Tabstop);
  270. }
  271.  
  272. ubyte *
  273. text_name()
  274. {
  275.     return(Ep->Name);
  276. }
  277.  
  278. void
  279. text_uninit()
  280. {
  281.     ED *ep = Ep;
  282.  
  283.     PMKill(ep);
  284.     freelist(ep->List, ep->Lines);
  285.     FreeMem(ep->List, ep->Maxlines * sizeof(char *));
  286.  
  287.     if (BEp == ep) {
  288.     BEp = NULL;
  289.     BSline = BEline = -1;
  290.     }
  291.     Remove((NODE *)ep);
  292.     if (ep->Font) {
  293.     SetFont(ep->Win->RPort, ep->Win->WScreen->RastPort.Font);
  294.     CloseFont(ep->Font);
  295.     }
  296.     UnLock((BPTR)ep->dirlock);
  297.     FreeMem(ep, sizeof(ED));
  298.     if (((ED *)DBase.mlh_Head)->Node.mln_Succ) {
  299.     Ep = (ED *)DBase.mlh_Head;
  300.     text_load();
  301.     } else {
  302.     Ep = NULL;
  303.     }
  304. }
  305.  
  306. void
  307. inversemode(n)
  308. {
  309.     RP *rp = Ep->Win->RPort;
  310.  
  311.     if (n) {
  312.     SetAPen(rp, ~Ep->BGPen);
  313.     SetDrMd(rp, JAM2|INVERSVID);
  314.     } else {
  315.     setpen(Ep->Line);
  316.     SetDrMd(rp, JAM2);
  317.     }
  318. }
  319.  
  320. void
  321. text_cursor(n)
  322. {
  323.     ED *ep = Ep;
  324.     RP *rp = ep->Win->RPort;
  325.  
  326.     movetocursor();
  327.     inversemode(n);
  328.     if (Current[ep->Column])
  329.     Text(rp, Current+ep->Column, 1);
  330.     else
  331.     Text(rp, " ", 1);
  332.     inversemode(0);
  333. }
  334.  
  335. void
  336. text_position(col, row)
  337. {
  338.     ED *ep = Ep;
  339.     text_sync();
  340.     if (col == 0)
  341.     col = -1;
  342.     ep->Column = ep->Topcolumn + col;
  343.     if (ep->Column > 254)
  344.     ep->Column = 254;
  345.     if (ep->Column < 0)
  346.     ep->Column = 0;
  347.     ep->Line = ep->Topline + row;
  348.     if (ep->Line >= ep->Lines)
  349.     ep->Line = ep->Lines - 1;
  350.     if (ep->Line < 0)
  351.     ep->Line = 0;
  352.     text_load();
  353.     text_sync();
  354. }
  355.  
  356. void
  357. displayblock(on)
  358. {
  359.     long start = Ep->Topline;
  360.     long lines = BEline - BSline + 1;
  361.  
  362.     if (start < BSline)
  363.     start = BSline;
  364.     if (!on) {
  365.     BSline = BEline = -1;
  366.     BEp = NULL;
  367.     }
  368.     if (Ep == BEp)
  369.     text_displayseg(start - Ep->Topline, lines);
  370. }
  371.  
  372. void
  373. text_redrawblock(ok)
  374. {
  375.     WIN *savewin = NULL;
  376.  
  377.     if (BEp) {
  378.     if (BEp != Ep) {
  379.         savewin = Ep->Win;
  380.         text_switch(BEp->Win);
  381.     }
  382.     if (BSline <= BEline && BSline >= 0 && BEline < Ep->Lines) {
  383.         if (!ok) {
  384.         BEp = NULL;
  385.         BSline = BEline = -1;
  386.         }
  387.         text_displayseg(0, Rows);
  388.     }
  389.     if (savewin)
  390.         text_switch(savewin);
  391.     }
  392.     if (!ok) {
  393.     BEp = NULL;
  394.     BSline = BEline = -1;
  395.     }
  396. }
  397.  
  398. void
  399. text_displayseg(start, n)
  400. {
  401.     short i, c;
  402.     ubyte *ptr;
  403.     ED *ep = Ep;
  404.     RP *rp = ep->Win->RPort;
  405.  
  406.     if (Nsu)
  407.     return;
  408.     for (i = start; i < start + n && i < Rows && ep->Topline + i < ep->Lines; ++i) {
  409.     if (Comlinemode) {
  410.         if (ep->Topline + i != ep->Line)
  411.         continue;
  412.         ptr = Current;
  413.         SetAPen(rp, ep->FGPen);
  414.     } else {
  415.         ptr = ep->List[ep->Topline + i];
  416.         setpen(i+ep->Topline);
  417.     }
  418.     for (c = ep->Topcolumn; c && *ptr; ++ptr, --c);
  419.     c = strlen(ptr);
  420.     if (c) {
  421.         Move(rp, COLT(0), ROWT(i));
  422.         Text(rp, ptr, (c > Columns) ? Columns : c);
  423.     }
  424.     }
  425. }
  426.  
  427. void
  428. text_redisplay()
  429. {
  430.     ED *ep = Ep;
  431.     RP *rp = ep->Win->RPort;
  432.  
  433.     if (Nsu)
  434.     return;
  435.     SetAPen(rp, ep->BGPen);
  436.     if (Comlinemode)
  437.     RectFill(rp, COL(0), ROW(Rows-1), Xbase + Xpixs - 1, Ybase + Ypixs - 1);
  438.     else
  439.     RectFill(rp, Xbase, Ybase, Xbase + Xpixs - 1, Ybase + Ypixs - 1);
  440.     text_displayseg(0,Rows);
  441. }
  442.  
  443. void
  444. text_redisplaycurrline()
  445. {
  446.     ED *ep = Ep;
  447.     RP *rp = ep->Win->RPort;
  448.  
  449.     int row = ep->Line - ep->Topline;
  450.  
  451.     if (Nsu)
  452.     return;
  453.     SetAPen(rp, ep->BGPen);
  454.     RectFill(rp, COL(0), ROW(row), Xbase + Xpixs - 1, ROW(row+1)-1);
  455.     text_displayseg(row, 1);
  456. }
  457.  
  458. void
  459. text_write(str)
  460. ubyte *str;
  461. {
  462.     short len = strlen(str);
  463.     short i;
  464.     ED *ep = Ep;
  465.     RP *rp = ep->Win->RPort;
  466.  
  467.     if (Clen + len >= 255) {
  468.     text_sync();
  469.     text_load();
  470.     }
  471.     if (ep->Insertmode == 0) {
  472.     if (ep->Column + len >= 255)
  473.         goto fail;
  474.     movmem(str, Current + ep->Column, len);
  475.     if (ep->Column + len >= Clen)
  476.         Clen = ep->Column + len;
  477.     Current[Clen] = 0;
  478.     } else {
  479.     if (Clen + len >= 255)
  480.         goto fail;
  481.     movmem(Current + ep->Column, Current + ep->Column + len, Clen+1-ep->Column);
  482.     movmem(str, Current + ep->Column, len);
  483.     Clen += len;
  484.     if (len < Columns - (ep->Column - ep->Topcolumn)) {
  485.         ScrollRaster(rp, -len * Xsize, 0 ,
  486.         COL(ep->Column - ep->Topcolumn),
  487.         ROW(ep->Line - ep->Topline),
  488.         COL(Columns) - 1,
  489.         ROW(ep->Line - ep->Topline + 1) - 1
  490.         );
  491.     }
  492.     }
  493.     i = (ep->Column - ep->Topcolumn + len > Columns) ? Columns - ep->Column + ep->Topcolumn : len;
  494.     setpen(ep->Line);
  495.     Move(rp, COLT(ep->Column - ep->Topcolumn), ROWT(ep->Line - ep->Topline));
  496.     Text(rp, str, i);
  497.     ep->Column += len;
  498.     if (ep->Column - ep->Topcolumn >= Columns)
  499.     text_sync();
  500. fail:
  501.     if (Comlinemode == 0 && ep->Wordwrap)
  502.     do_reformat(0);
  503. }
  504.  
  505. void
  506. do_up()
  507. {
  508.     ED *ep = Ep;
  509.     RP *rp = ep->Win->RPort;
  510.  
  511.     if (ep->Line) {
  512.     text_sync();
  513.     --ep->Line;
  514.     text_load();
  515.     if (Ep->Line < Ep->Topline) {
  516.         if (Nsu == 0) {
  517.         ScrollRaster(rp,0,-Ysize,COL(0),ROW(0),COL(Columns)-1,ROW(Rows)-1);
  518.         --ep->Topline;
  519.         text_displayseg(0, 1);
  520.         }
  521.     }
  522.     } else {
  523.     Abortcommand = 1;
  524.     }
  525. }
  526.  
  527. void
  528. do_scrolldown()
  529. {
  530.     ED *ep = Ep;
  531.     RP *rp = ep->Win->RPort;
  532.  
  533.     if (ep->Topline + Rows < ep->Lines) {
  534.     if (Nsu == 0) {
  535.         text_sync();
  536.         ScrollRaster(rp,0,Ysize,COL(0),ROW(0),COL(Columns)-1,ROW(Rows)-1);
  537.         ++ep->Topline;
  538.         ++ep->Line;
  539.         text_load();
  540.         text_displayseg(Rows-1, 1);
  541.     }
  542.     } else {
  543.     Abortcommand = 1;
  544.     }
  545. }
  546.  
  547. void
  548. do_scrollup()
  549. {
  550.     ED *ep = Ep;
  551.     RP *rp = ep->Win->RPort;
  552.  
  553.     if (ep->Topline) {
  554.     if (Nsu == 0) {
  555.         text_sync();
  556.         ScrollRaster(rp,0,-Ysize,COL(0),ROW(0),COL(Columns)-1,ROW(Rows)-1);
  557.         --ep->Topline;
  558.         --ep->Line;
  559.         text_load();
  560.         text_displayseg(0, 1);
  561.     }
  562.     } else {
  563.     Abortcommand = 1;
  564.     }
  565. }
  566.  
  567. void
  568. do_down()
  569. {
  570.     ED *ep = Ep;
  571.     RP *rp = ep->Win->RPort;
  572.  
  573.     if (ep->Line + 1 < ep->Lines) {
  574.     text_sync();
  575.     ++ep->Line;
  576.     text_load();
  577.     if (ep->Line - ep->Topline >= Rows) {
  578.         if (Nsu == 0) {
  579.         ScrollRaster(rp,0,Ysize,COL(0),ROW(0),COL(Columns)-1,ROW(Rows)-1);
  580.         ++ep->Topline;
  581.         text_displayseg(Rows-1, 1);
  582.         }
  583.     }
  584.     } else {
  585.     Abortcommand = 1;
  586.     }
  587. }
  588.  
  589. /*
  590.  *  PAGEUP
  591.  *  PAGEDOWN
  592.  *  PAGESET n    (n = 0 to 100 for percentage of #rows to scroll, minimum 1)
  593.  *        can be > 100.
  594.  */
  595.  
  596. void
  597. do_page()
  598. {
  599.     int n, multiplier = 1;
  600.     ED *ep = Ep;
  601.     static short pctg = 80;
  602.  
  603.     switch(av[0][4]) {
  604.     case 'u':
  605.     multiplier = -1;
  606.     case 'd':
  607.     n = multiplier * Rows * pctg / 100;
  608.     if (!n)
  609.         n = multiplier;
  610.     if (n > 0 && ep->Topline >= ep->Lines - Rows)
  611.         return;
  612.     text_sync();
  613.     ep->Line += n;
  614.     ep->Topline += n;
  615.     if (ep->Line >= ep->Lines)
  616.         ep->Line = ep->Lines - 1;
  617.     if (ep->Line < 0)
  618.         ep->Line = 0;
  619.     if (ep->Topline >= ep->Lines)
  620.         ep->Topline = ep->Lines - Rows - 1;
  621.     if (ep->Topline < 0)
  622.         ep->Topline = 0;
  623.     text_load();
  624.     if (!text_sync())
  625.         text_redisplay();
  626.     break;
  627.     case 's':
  628.     pctg = atoi(av[1]);
  629.     break;
  630.     }
  631. }
  632.  
  633. void
  634. do_downadd()
  635. {
  636.     ED *ep = Ep;
  637.     ubyte *ptr;
  638.  
  639.     if (ep->Line + 1 == ep->Lines) {
  640.     ep->Modified = 1;
  641.     if (makeroom(32) && (ptr = allocb(1))) {
  642.         ep->List[ep->Lines] = ptr;
  643.         *ptr = 0;
  644.         ++ep->Lines;
  645.     } else {
  646.         nomemory();
  647.     }
  648.     }
  649.     do_down();
  650. }
  651.  
  652. void
  653. do_left()
  654. {
  655.     ED *ep = Ep;
  656.  
  657.     if (ep->Column) {
  658.     --ep->Column;
  659.     if (ep->Column < ep->Topcolumn)
  660.         text_sync();
  661.     } else {
  662.     Abortcommand = 1;
  663.     }
  664. }
  665.  
  666. void
  667. do_right()
  668. {
  669.     ED *ep = Ep;
  670.  
  671.     if (ep->Column != 254) {
  672.     if (Current[ep->Column] == 0) {
  673.         Current[ep->Column] = ' ';
  674.         Current[ep->Column+1]= '\0';
  675.         ++Clen;
  676.     }
  677.     ++ep->Column;
  678.     if (ep->Column - ep->Topcolumn >= Columns)
  679.         text_sync();
  680.     } else {
  681.     Abortcommand = 1;
  682.     }
  683. }
  684.  
  685. void
  686. do_tab()
  687. {
  688.     short n;
  689.     ED *ep = Ep;
  690.  
  691.     for (n = ep->Tabstop-(ep->Column % ep->Tabstop); n > 0; --n)
  692.     do_right();
  693. }
  694.  
  695. void
  696. do_backtab()
  697. {
  698.     short n;
  699.     ED *ep = Ep;
  700.  
  701.     n = ep->Column % ep->Tabstop;
  702.     if (!n)
  703.     n = ep->Tabstop;
  704.     for (; n > 0; --n)
  705.     do_left();
  706. }
  707.  
  708. void
  709. do_return()
  710. {
  711.     ubyte buf[256];
  712.     char *partial;
  713.  
  714.     if (Comlinemode) {
  715.     strcpy(buf, Current);
  716.     strcpy(RecallBuf, Current);
  717.     partial = Partial;
  718.     Partial = NULL;
  719.     escapecomlinemode();
  720.     if (partial) {
  721.         if (do_command(buf))
  722.         do_command(partial);
  723.         free(partial);
  724.     } else {
  725.         do_command(buf);
  726.     }
  727.     } else {
  728.     Ep->Column = 0;
  729.     text_sync();
  730.     do_downadd();
  731.     }
  732. }
  733.  
  734. void
  735. do_bs()
  736. {
  737.     ED *ep = Ep;
  738.     RP *rp = ep->Win->RPort;
  739.  
  740.     if (ep->Column) {
  741.     movmem(Current + ep->Column, Current + ep->Column - 1, Clen - ep->Column + 1);
  742.     --ep->Column;
  743.     --Clen;
  744.     if (ep->Column < ep->Topcolumn) {
  745.         text_sync();
  746.     } else {
  747.         ScrollRaster(rp, Xsize, 0,
  748.         COL(ep->Column - ep->Topcolumn),
  749.         ROW(ep->Line   - ep->Topline),
  750.         COL(Columns)-1,
  751.         ROW(ep->Line - ep->Topline + 1)-1
  752.         );
  753.         if (Clen >= ep->Topcolumn + Columns) {
  754.         setpen(ep->Line);
  755.         Move(rp, COLT(Columns-1), ROWT(ep->Line - ep->Topline));
  756.         Text(rp, Current + ep->Topcolumn + Columns - 1, 1);
  757.         }
  758.     }
  759.     if (Comlinemode == 0 && ep->Wordwrap)
  760.         do_reformat(0);
  761.     } else {
  762.     Abortcommand = 1;
  763.     }
  764. }
  765.  
  766.  
  767. /*
  768.  * esc, escimm
  769.  */
  770.  
  771. int Savetopline, Savecolumn, Savetopcolumn;
  772.  
  773. void
  774. do_recall()
  775. {
  776.     av[0] = (ubyte *)"escimm";
  777.     av[1] = (ubyte *)RecallBuf;
  778.     do_esc();
  779. }
  780.  
  781. void
  782. do_esc()
  783. {
  784.     ED *ep = Ep;
  785.     RP *rp = ep->Win->RPort;
  786.  
  787.     if (Comlinemode) {
  788.     escapecomlinemode();
  789.     return;
  790.     }
  791.     text_sync();
  792.     if (av[0][3] == 'i')
  793.     strcpy(Current, av[1]);
  794.     else
  795.     Current[0] = 0;
  796.     Clen = strlen(Current);
  797.     Comlinemode = 1;
  798.     returnoveride(1);
  799.     Savetopline = ep->Topline;
  800.     Savecolumn    = ep->Column;
  801.     Savetopcolumn = ep->Topcolumn;
  802.     ep->Column      = Clen;
  803.     ep->Topcolumn = 0;
  804.     ep->Topline   = ep->Line - Rows + 1;
  805.     SetAPen(rp, ep->BGPen);
  806.     RectFill(rp, COL(0), ROW(Rows-1), Xbase + Xpixs - 1, Ybase + Ypixs - 1);
  807.     SetAPen(rp, ep->FGPen);
  808.     Move(rp, COL(0), ROW(Rows-1) - 1);
  809.     Draw(rp, Xbase + Xpixs - 1, ROW(Rows - 1) - 1);
  810.     text_displayseg(Rows - 1, 1);
  811. }
  812.  
  813. void
  814. escapecomlinemode()
  815. {
  816.     ED *ep = Ep;
  817.     RP *rp = ep->Win->RPort;
  818.  
  819.     if (Partial) {
  820.     free(Partial);
  821.     Partial = NULL;
  822.     }
  823.     if (Comlinemode) {
  824.     strcpy(RecallBuf, Current);
  825.     Comlinemode = 0;
  826.     returnoveride(0);
  827.     ep->Topline = Savetopline;
  828.     ep->Column  = Savecolumn;
  829.     ep->Topcolumn = Savetopcolumn;
  830.     text_load();
  831.     SetAPen(rp, ep->BGPen);
  832.     RectFill(rp, COL(0), ROW(Rows-1)-1, Xbase + Xpixs - 1, Ybase + Ypixs - 1);
  833.     SetAPen(rp, ep->FGPen);
  834.     text_displayseg(Rows - 2, 2);
  835.     }
  836. }
  837.  
  838. void
  839. do_del()
  840. {
  841.     ED *ep = Ep;
  842.     RP *rp = ep->Win->RPort;
  843.  
  844.     if (Current[ep->Column]) {
  845.     movmem(Current + ep->Column + 1, Current + ep->Column, Clen - ep->Column);
  846.     --Clen;
  847.     ScrollRaster(rp, Xsize, 0,
  848.         COL(ep->Column - ep->Topcolumn),
  849.         ROW(ep->Line - ep->Topline),
  850.         COL(Columns)-1,
  851.         ROW(ep->Line - ep->Topline + 1) - 1
  852.     );
  853.     if (Clen >= ep->Topcolumn + Columns) {
  854.         setpen(ep->Line);
  855.         Move(rp, COLT(Columns-1), ROWT(ep->Line-ep->Topline));
  856.         Text(rp, Current+ep->Topcolumn+Columns-1, 1);
  857.     }
  858.     if (Comlinemode == 0 && ep->Wordwrap)
  859.         do_reformat(0);
  860.     }
  861. }
  862.  
  863. void
  864. do_top()
  865. {
  866.     text_sync();
  867.     Ep->Line = 0;
  868.     text_load();
  869.     text_sync();
  870. }
  871.  
  872. void
  873. do_bottom()
  874. {
  875.     text_sync();
  876.     Ep->Line = Ep->Lines - 1;
  877.     text_load();
  878.     text_sync();
  879. }
  880.  
  881. void
  882. do_firstcolumn()
  883. {
  884.     if (Ep->Column) {
  885.     Ep->Column = 0;
  886.     text_sync();
  887.     }
  888. }
  889.  
  890. void
  891. do_firstnb()
  892. {
  893.     for (Ep->Column = 0; Current[Ep->Column] == ' '; ++Ep->Column);
  894.     if (Current[Ep->Column] == 0)
  895.     Ep->Column = 0;
  896.     text_sync();
  897. }
  898.  
  899. void
  900. do_lastcolumn()
  901. {
  902.     short i;
  903.  
  904.     text_sync();
  905.     i = (Comlinemode) ? Clen : strlen(Ep->List[Ep->Line]);
  906.     if (i != Ep->Column) {
  907.     Ep->Column = i;
  908.     text_sync();
  909.     }
  910. }
  911.  
  912. /*
  913.  * GOTO [+/-]N
  914.  * GOTO BLOCK    start of block
  915.  * GOTO START    start of block
  916.  * GOTO END    end of block
  917.  */
  918.  
  919. void
  920. do_goto()
  921. {
  922.     long n, i;
  923.     ubyte *ptr = av[1];
  924.  
  925.     i = 0;
  926.     n = -1;
  927.  
  928.     switch(*ptr) {
  929.     case 'b':
  930.     case 's':
  931.     case 'B':
  932.     case 'S':
  933.     n = -1;
  934.     if (Ep == BEp)
  935.         n = BSline;
  936.     break;
  937.     case 'e':
  938.     case 'E':
  939.     n = -1;
  940.     if (Ep == BEp)
  941.         n = BEline;
  942.     break;
  943.     case '+':
  944.     i = 1;
  945.     case '-':
  946.     n = Ep->Line;
  947.     default:
  948.     n += atoi(ptr+i);
  949.     }
  950.     if (n >= Ep->Lines)
  951.     n = Ep->Lines - 1;
  952.     if (n < 0)
  953.     n = 0;
  954.     text_sync();
  955.     Ep->Line = n;
  956.     text_load();
  957.     text_sync();
  958. }
  959.  
  960. void
  961. do_screentop()
  962. {
  963.     text_sync();
  964.     Ep->Line = Ep->Topline;
  965.     text_load();
  966.     text_sync();
  967. }
  968.  
  969. void
  970. do_screenbottom()
  971. {
  972.     text_sync();
  973.     Ep->Line = Ep->Topline + Rows - 1;
  974.     if (Ep->Line < 0 || Ep->Line >= Ep->Lines)
  975.     Ep->Line = Ep->Lines - 1;
  976.     text_load();
  977.     text_sync();
  978. }
  979.  
  980. static ubyte Fstr[256];
  981. static ubyte Rstr[256];
  982. static short Srch_sign;
  983. static char Doreplace;
  984.  
  985. /*
  986.  * findstr, repstr
  987.  */
  988.  
  989. void
  990. do_findstr()
  991. {
  992.     if (av[0][0] == 'f')
  993.     strcpy(Fstr, av[1]);
  994.     else
  995.     strcpy(Rstr, av[1]);
  996. }
  997.  
  998. /*
  999.  * findr, nextr, prevr
  1000.  */
  1001.  
  1002. void
  1003. do_findr()
  1004. {
  1005.     Doreplace = 1;
  1006.     Srch_sign = 1;
  1007.     switch(av[0][0]) {
  1008.     case 'f':
  1009.     strcpy(Fstr, av[1]);
  1010.     strcpy(Rstr, av[2]);
  1011.     break;
  1012.     case 'p':
  1013.     Srch_sign = -1;
  1014.     break;
  1015.     }
  1016.     search_operation();
  1017. }
  1018.  
  1019. /*
  1020.  * find, next, prev
  1021.  */
  1022.  
  1023. void
  1024. do_find()
  1025. {
  1026.     Doreplace = 0;
  1027.     Srch_sign = 1;
  1028.     switch(av[0][0]) {
  1029.     case 'f':
  1030.     strcpy(Fstr, av[1]);
  1031.     break;
  1032.     case 'p':
  1033.     Srch_sign = -1;
  1034.     break;
  1035.     }
  1036.     search_operation();
  1037. }
  1038.  
  1039.  
  1040. static char CaseIgnore;
  1041.  
  1042. void
  1043. search_operation()
  1044. {
  1045.     int flen = strlen(Fstr);
  1046.     int rlen = strlen(Rstr);
  1047.     char senabled = 0;
  1048.     ubyte *ptr;
  1049.     int i, col;
  1050.     ED *ep = Ep;
  1051.  
  1052.     CaseIgnore = ep->IgnoreCase;
  1053.     text_sync();
  1054.     if (!flen) {
  1055.     title("No find pattern");
  1056.     Abortcommand = 1;
  1057.     return;
  1058.     }
  1059.  
  1060.     col = ep->Column;
  1061.     if (col >= strlen(ep->List[ep->Line]))
  1062.     col = strlen(ep->List[ep->Line]);
  1063.     for (i = ep->Line;;) {
  1064.     ptr = ep->List[i];
  1065.     if (Srch_sign > 0) {
  1066.         while (ptr[col]) {
  1067.         if (senabled && case_strncmp(Fstr,ptr+col,flen) == 0)
  1068.             goto found;
  1069.         senabled = 1;
  1070.         ++col;
  1071.         }
  1072.         senabled = 1;
  1073.         if (++i >= ep->Lines)
  1074.         break;
  1075.         col = 0;
  1076.     } else {
  1077.         while (col >= 0) {
  1078.         if (senabled && case_strncmp(Fstr,ptr+col,flen) == 0)
  1079.             goto found;
  1080.         senabled = 1;
  1081.         --col;
  1082.         }
  1083.         senabled = 1;
  1084.         if (--i < 0)
  1085.         break;
  1086.         col = strlen(ep->List[i]);
  1087.     }
  1088.     }
  1089.     title("Pattern Not Found");
  1090.     Abortcommand = 1;
  1091.     return;
  1092.  
  1093. found:
  1094.     ep->Line = i;
  1095.     ep->Column = col;
  1096.  
  1097.     text_load();
  1098.     if (Doreplace) {
  1099.     if (rlen > flen && rlen-flen+strlen(ptr) > 254) {
  1100.         title("Replace: Line Too Long");
  1101.         Abortcommand = 1;
  1102.         return;
  1103.     }
  1104.     if (Clen-col-flen >= 0) {
  1105.         movmem(Current+col+flen, Current+col+rlen, Clen-col-flen+1);
  1106.         movmem(Rstr, Current+col, rlen);
  1107.         Clen += rlen-flen;
  1108.         ep->Column += rlen;
  1109.     }
  1110.     text_sync();
  1111.     text_redisplaycurrline();
  1112.     } else {
  1113.     text_sync();
  1114.     }
  1115. }
  1116.  
  1117. case_strncmp(s1, s2, len)
  1118. char *s1, *s2;
  1119. {
  1120.     if (CaseIgnore == 0)
  1121.     return(strncmp(s1, s2, len));
  1122.     for (; len; --len, ++s1, ++s2) {
  1123.     if ((*s1|0x20) != (*s2|0x20))
  1124.         return(1);
  1125.     if (((*s1 >= 'a' && *s1 <= 'z') || (*s1 >= 'A' && *s1 <= 'Z')) &&
  1126.         ((*s2 >= 'a' && *s2 <= 'z') || (*s2 >= 'A' && *s2 <= 'Z')))
  1127.     {
  1128.         continue;
  1129.     }
  1130.     if (*s1 != *s2)
  1131.         return(1);
  1132.     }
  1133.     return(0);
  1134. }
  1135.  
  1136.  
  1137. static ubyte brackets[][2] = {
  1138.     '(',    ')',
  1139.     '{',    '}',
  1140.     '[',    ']',
  1141.     '<',    '>',
  1142.     '`',    '\'',
  1143.     0
  1144. };
  1145.  
  1146. void
  1147. do_findmatch()
  1148. {
  1149.     ubyte c, c2;
  1150.     ubyte *lineptr;
  1151.     short direction = 0, i;
  1152.     long cnt = 0;
  1153.     long line, column;
  1154.     long endline, endcol, col, len;
  1155.  
  1156.     line = Ep->Line;
  1157.     column = Ep->Column;
  1158.     c = Current[column];
  1159.  
  1160.     for (i = 0; brackets[i][0]; i++) {
  1161.     if (brackets[i][0] == c) {    /* forward  */
  1162.         c2 = brackets[i][1];
  1163.         direction = 1;
  1164.         endline = Ep->Lines - 1;
  1165.         break;
  1166.     }
  1167.     if (brackets[i][1] == c) {    /* backward */
  1168.         c2 = brackets[i][0];
  1169.         direction = -1;
  1170.         endline = 0;
  1171.         break;
  1172.     }
  1173.     }
  1174.  
  1175.     if (direction == 0) {
  1176.     title("not matchable character");
  1177.     return;
  1178.     }
  1179.  
  1180.     for ( ; line != endline + direction; line += direction) {
  1181.  
  1182.     if (cnt == 0) {
  1183.         lineptr = Current;        /* current line (we're just starting) */
  1184.         len = Clen;
  1185.         col = column;
  1186.     } else {
  1187.         lineptr = Ep->List[line];
  1188.         len = strlen(lineptr);
  1189.         col = (direction == 1) ? 0 : len - 1;
  1190.     }
  1191.     endcol = (direction == 1) ? len - 1 : 0;
  1192.  
  1193.     for ( ; col != endcol + direction; col += direction) {
  1194.         if (lineptr[col] == c)
  1195.         cnt++;
  1196.         else if (lineptr[col] == c2) {
  1197.         cnt--;
  1198.         if (cnt == 0) {     /* found match!!          */
  1199.             text_sync();    /* ok, now update buffers */
  1200.             Ep->Line = line;
  1201.             Ep->Column = col;
  1202.             text_load();    /* and move to new place  */
  1203.             text_sync();
  1204.             return;
  1205.         }
  1206.         }
  1207.     }
  1208.     }
  1209.     title("match not found");
  1210. }
  1211.  
  1212. /*
  1213.  *  Change to window by filepath, open new window and load new file
  1214.  *  if window cannot be found.
  1215.  */
  1216.  
  1217. void
  1218. do_window()
  1219. {
  1220.     ED *ed;
  1221.     char buf[128];
  1222.  
  1223.     if ((ed = finded(av[1], 0)) == NULL) {
  1224.     sprintf(buf, "newwindow newfile (%s)", av[1]);
  1225.     do_command(buf);
  1226.     ed = finded(av[1], 0);
  1227.     } else {
  1228.     WindowToFront(ed->Win);
  1229.     ActivateWindow(ed->Win);
  1230.     }
  1231.     if (ed == NULL) {
  1232.     title("unable to load file");
  1233.     } else {
  1234.     text_switch(ed->Win);
  1235.     if (Ep->iconmode)
  1236.         uniconify();
  1237.     else
  1238.         text_cursor(0);
  1239.     }
  1240. }
  1241.  
  1242.